/*
	Протокол для связи
*/
#include "defines.h"
extern U8 own_hw_adr[];
extern LOCALM localm[];
/*
	Парсим данные
*/

void link_parse_packet(U8 * packet, U16 packet_size, U8 socket)
{
	//Вычисляем значение поля length
	U16 length = *((U16 *)&packet[LINK_LENGTH]);

	//Пакет должен как минимимум содержать заголовок		
	if ((length>=LINK_HEADER_SIZE)&&(packet_size>=length))
	{
		
		//Смотрим коды команд
		switch(packet[LINK_TYPE])
		{
			case CMD_GET_INFO:						cmd_get_info(packet,length,socket);			break;
			case CMD_JUMP_TO_BOOTLOADER:			cmd_jumpto_bootloader(packet,length,socket);		break;	
						
			default:		ans_error(packet[LINK_TYPE],ERROR_NOT_SUPPORTED,socket);		break;
			
		}
	}
	//Посылаем ошибку
	else
		ans_error(packet[LINK_TYPE],ERROR_LENGTH_FIELD,socket);
}
/*
	Выдадим информацию об устройстве
*/
void cmd_get_info(U8 * packet, U16 length, U8 socket)
{
	SER_PutStr("get info\r\n");
	if (length==LINK_HEADER_SIZE)
	{
		char str[100];
		char * p = FW_VER;
		memset(str,0x00,sizeof(str));
		sprintf(str,"FW=%s\r\nSN=%02x%02x%02x%02x%02x%02x\r\n",p,own_hw_adr[0],own_hw_adr[1],own_hw_adr[2],own_hw_adr[3],own_hw_adr[4],own_hw_adr[5]);
		//Отправлеяем ответ
		link_send_packet(ANS_INFO,str,strlen(str),socket);
	}
	else
		ans_error(packet[LINK_TYPE],ERROR_LENGTH_FIELD,socket);
}

/*
	Прыгаем на приложение
*/
void cmd_jumpto_bootloader(U8 * packet, U16 length, U8 socket)
{
	if (length==LINK_HEADER_SIZE)
	{
			
			//останавливаем таймер
			system_timer_stop();
			
			//Записываем текущие сетевые параметры
			prepare_sector(NETPARAMS_SECTOR,NETPARAMS_SECTOR);
			erase_sector(NETPARAMS_SECTOR,NETPARAMS_SECTOR);
			prepare_sector(NETPARAMS_SECTOR,NETPARAMS_SECTOR);
			//пишем только 12 байт - остальные нам не нужны
			memset(tcp_send_buffer,0x00,sizeof(tcp_send_buffer));
			memcpy(tcp_send_buffer,&localm[NETIF_ETH],12);
			write_data(NETPARAMS_ADDRESS,(U32 *)tcp_send_buffer,1024);
			
			//Сброс через Watchdog
			LPC_WDT->WDTC = 0x00000FFF; // very short timeout
			LPC_WDT->WDMOD = 0x03; // watchdog resets CPU
			LPC_WDT->WDFEED = 0xAA; // start watchdog
			LPC_WDT->WDFEED = 0x55;
			//Ответа нет...
	}	
	else
		ans_error(packet[LINK_TYPE],ERROR_LENGTH_FIELD,socket);	
	
}

/*
	Отправляем ОК
*/
void ans_ok(U8 type,U8 sock)
{
	link_send_packet(ANS_OK,(U8*)&type,sizeof(type),sock);
}

/*
	Отправляем ошибку
*/
void ans_error(U8 type, U8 error,U8 sock)
{
	U8 err[2];
	err[0] = type;
	err[1] = error;
	link_send_packet(ANS_ERROR,(U8*)&err,sizeof(err),sock);
}



void link_send_packet(uint8_t type, uint8_t * data, uint16_t data_length,U8 sock)
{
	//Выделяем память под новый пакет = данные + заголовок
	uint8_t packet[260];
	
	//Формируем поле LENGTH
	uint16_t length= data_length+LINK_HEADER_SIZE;
	memcpy(packet, (uint8_t *)&(length),sizeof(length));
	//Поле type
	packet[LINK_TYPE] = type;

	//Копируем данные 
	memcpy(packet+LINK_DATA,data,data_length);

	//Отправляем пакет
	if (!udpActive)
		tcp_send_data(packet,data_length+LINK_HEADER_SIZE,sock);
	else
		udp_send_data(packet,data_length+LINK_HEADER_SIZE,sock);
}